﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
using System.Configuration;
using System.Text.RegularExpressions;
using System.Xml;
using System.Data;
using System.Net.Mail;
using System.Net;

namespace NDEngineering.Utilities
{
    public class Utils
    {
        /// <summary>
        /// HMAC MD5
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string HMAC_MD5(string key, string value)
        {
            // The first two lines take the input values and convert them from strings to Byte arrays
            byte[] HMACkey = (new System.Text.ASCIIEncoding()).GetBytes(key);
            byte[] HMACdata = (new System.Text.ASCIIEncoding()).GetBytes(value);

            // create a HMACMD5 object with the key set
            HMACMD5 myhmacMD5 = new HMACMD5(HMACkey);

            //calculate the hash (returns a byte array)
            byte[] HMAChash = myhmacMD5.ComputeHash(HMACdata);

            //loop through the byte array and add append each piece to a string to obtain a hash string
            string fingerprint = "";
            for (int i = 0; i < HMAChash.Length; i++)
            {
                fingerprint += HMAChash[i].ToString("x").PadLeft(2, '0');
            }

            return fingerprint;
        }

        /// <summary>
        /// Encrypt a byte array into a byte array using a key and an IV 
        /// </summary>
        /// <param name="clearData"></param>
        /// <param name="Key"></param>
        /// <param name="IV"></param>
        /// <returns></returns>
        public static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
        {
            // Create a MemoryStream to accept the encrypted bytes 
            MemoryStream ms = new MemoryStream();

            // Create a symmetric algorithm. 
            // We are going to use Rijndael because it is strong and
            // available on all platforms. 
            // You can use other algorithms, to do so substitute the
            // next line with something like 
            //      TripleDES alg = TripleDES.Create(); 
            Rijndael alg = Rijndael.Create();

            // Now set the key and the IV. 
            // We need the IV (Initialization Vector) because
            // the algorithm is operating in its default 
            // mode called CBC (Cipher Block Chaining).
            // The IV is XORed with the first block (8 byte) 
            // of the data before it is encrypted, and then each
            // encrypted block is XORed with the 
            // following block of plaintext.
            // This is done to make encryption more secure. 

            // There is also a mode called ECB which does not need an IV,
            // but it is much less secure. 
            alg.Key = Key;
            alg.IV = IV;

            // Create a CryptoStream through which we are going to be
            // pumping our data. 
            // CryptoStreamMode.Write means that we are going to be
            // writing data to the stream and the output will be written
            // in the MemoryStream we have provided. 
            CryptoStream cs = new CryptoStream(ms,
               alg.CreateEncryptor(), CryptoStreamMode.Write);

            // Write the data and make it do the encryption 
            cs.Write(clearData, 0, clearData.Length);

            // Close the crypto stream (or do FlushFinalBlock). 
            // This will tell it that we have done our encryption and
            // there is no more data coming in, 
            // and it is now a good time to apply the padding and
            // finalize the encryption process. 
            cs.Close();

            // Now get the encrypted data from the MemoryStream.
            // Some people make a mistake of using GetBuffer() here,
            // which is not the right way. 
            byte[] encryptedData = ms.ToArray();

            return encryptedData;
        }

        /// <summary>
        /// Encrypt a string into a string using a password 
        /// </summary>
        /// <param name="clearText"></param>
        /// <param name="Password"></param>
        /// <returns></returns>
        public static string Encrypt(string clearText, string Password)
        {
            // First we need to turn the input string into a byte array. 
            byte[] clearBytes =
              System.Text.Encoding.Unicode.GetBytes(clearText);

            // Then, we need to turn the password into Key and IV 
            // We are using salt to make it harder to guess our key
            // using a dictionary attack - 
            // trying to guess a password by enumerating all possible words. 
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
                new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
            0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

            // Now get the key/IV and do the encryption using the
            // function that accepts byte arrays. 
            // Using PasswordDeriveBytes object we are first getting
            // 32 bytes for the Key 
            // (the default Rijndael key length is 256bit = 32bytes)
            // and then 16 bytes for the IV. 
            // IV should always be the block size, which is by default
            // 16 bytes (128 bit) for Rijndael. 
            // If you are using DES/TripleDES/RC2 the block size is
            // 8 bytes and so should be the IV size. 
            // You can also read KeySize/BlockSize properties off
            // the algorithm to find out the sizes. 
            byte[] encryptedData = Encrypt(clearBytes,
                     pdb.GetBytes(32), pdb.GetBytes(16));

            // Now we need to turn the resulting byte array into a string. 
            // A common mistake would be to use an Encoding class for that.
            //It does not work because not all byte values can be
            // represented by characters. 
            // We are going to be using Base64 encoding that is designed
            //exactly for what we are trying to do. 
            return Convert.ToBase64String(encryptedData);

        }


        /// <summary>
        /// Encrypt bytes into bytes using a password 
        /// </summary>
        /// <param name="clearData"></param>
        /// <param name="Password"></param>
        /// <returns></returns>
        public static byte[] Encrypt(byte[] clearData, string Password)
        {
            // We need to turn the password into Key and IV. 
            // We are using salt to make it harder to guess our key
            // using a dictionary attack - 
            // trying to guess a password by enumerating all possible words. 
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
                new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
            0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

            // Now get the key/IV and do the encryption using the function
            // that accepts byte arrays. 
            // Using PasswordDeriveBytes object we are first getting
            // 32 bytes for the Key 
            // (the default Rijndael key length is 256bit = 32bytes)
            // and then 16 bytes for the IV. 
            // IV should always be the block size, which is by default
            // 16 bytes (128 bit) for Rijndael. 
            // If you are using DES/TripleDES/RC2 the block size is 8
            // bytes and so should be the IV size. 
            // You can also read KeySize/BlockSize properties off the
            // algorithm to find out the sizes. 
            return Encrypt(clearData, pdb.GetBytes(32), pdb.GetBytes(16));

        }

        /// <summary>
        /// Encrypt a file into another file using a password 
        /// </summary>
        /// <param name="fileIn"></param>
        /// <param name="fileOut"></param>
        /// <param name="Password"></param>
        public static void Encrypt(string fileIn,
                    string fileOut, string Password)
        {

            // First we are going to open the file streams 
            FileStream fsIn = new FileStream(fileIn,
                FileMode.Open, FileAccess.Read);
            FileStream fsOut = new FileStream(fileOut,
                FileMode.OpenOrCreate, FileAccess.Write);

            // Then we are going to derive a Key and an IV from the
            // Password and create an algorithm 
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
                new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
            0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

            Rijndael alg = Rijndael.Create();
            alg.Key = pdb.GetBytes(32);
            alg.IV = pdb.GetBytes(16);

            // Now create a crypto stream through which we are going
            // to be pumping data. 
            // Our fileOut is going to be receiving the encrypted bytes. 
            CryptoStream cs = new CryptoStream(fsOut,
                alg.CreateEncryptor(), CryptoStreamMode.Write);

            // Now will will initialize a buffer and will be processing
            // the input file in chunks. 
            // This is done to avoid reading the whole file (which can
            // be huge) into memory. 
            int bufferLen = 4096;
            byte[] buffer = new byte[bufferLen];
            int bytesRead;

            do
            {
                // read a chunk of data from the input file 
                bytesRead = fsIn.Read(buffer, 0, bufferLen);

                // encrypt it 
                cs.Write(buffer, 0, bytesRead);
            } while (bytesRead != 0);

            // close everything 

            // this will also close the unrelying fsOut stream
            cs.Close();
            fsIn.Close();
        }

        /// <summary>
        /// Decrypt a byte array into a byte array using a key and an IV 
        /// </summary>
        /// <param name="cipherData"></param>
        /// <param name="Key"></param>
        /// <param name="IV"></param>
        /// <returns></returns>
        public static byte[] Decrypt(byte[] cipherData,
                                    byte[] Key, byte[] IV)
        {
            // Create a MemoryStream that is going to accept the
            // decrypted bytes 
            MemoryStream ms = new MemoryStream();

            // Create a symmetric algorithm. 
            // We are going to use Rijndael because it is strong and
            // available on all platforms. 
            // You can use other algorithms, to do so substitute the next
            // line with something like 
            //     TripleDES alg = TripleDES.Create(); 
            Rijndael alg = Rijndael.Create();

            // Now set the key and the IV. 
            // We need the IV (Initialization Vector) because the algorithm
            // is operating in its default 
            // mode called CBC (Cipher Block Chaining). The IV is XORed with
            // the first block (8 byte) 
            // of the data after it is decrypted, and then each decrypted
            // block is XORed with the previous 
            // cipher block. This is done to make encryption more secure. 
            // There is also a mode called ECB which does not need an IV,
            // but it is much less secure. 
            alg.Key = Key;
            alg.IV = IV;

            // Create a CryptoStream through which we are going to be
            // pumping our data. 
            // CryptoStreamMode.Write means that we are going to be
            // writing data to the stream 
            // and the output will be written in the MemoryStream
            // we have provided. 
            CryptoStream cs = new CryptoStream(ms,
                alg.CreateDecryptor(), CryptoStreamMode.Write);

            // Write the data and make it do the decryption 
            cs.Write(cipherData, 0, cipherData.Length);

            // Close the crypto stream (or do FlushFinalBlock). 
            // This will tell it that we have done our decryption
            // and there is no more data coming in, 
            // and it is now a good time to remove the padding
            // and finalize the decryption process. 
            cs.Close();

            // Now get the decrypted data from the MemoryStream. 
            // Some people make a mistake of using GetBuffer() here,
            // which is not the right way. 
            byte[] decryptedData = ms.ToArray();

            return decryptedData;
        }

        /// <summary>
        /// Decrypt a string into a string using a password 
        /// </summary>
        /// <param name="cipherText"></param>
        /// <param name="Password"></param>
        /// <returns></returns>
        public static string Decrypt(string cipherText, string Password)
        {
            // First we need to turn the input string into a byte array. 
            // We presume that Base64 encoding was used 
            byte[] cipherBytes = Convert.FromBase64String(cipherText);

            // Then, we need to turn the password into Key and IV 
            // We are using salt to make it harder to guess our key
            // using a dictionary attack - 
            // trying to guess a password by enumerating all possible words. 
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
                new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 
            0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

            // Now get the key/IV and do the decryption using
            // the function that accepts byte arrays. 
            // Using PasswordDeriveBytes object we are first
            // getting 32 bytes for the Key 
            // (the default Rijndael key length is 256bit = 32bytes)
            // and then 16 bytes for the IV. 
            // IV should always be the block size, which is by
            // default 16 bytes (128 bit) for Rijndael. 
            // If you are using DES/TripleDES/RC2 the block size is
            // 8 bytes and so should be the IV size. 
            // You can also read KeySize/BlockSize properties off
            // the algorithm to find out the sizes. 
            byte[] decryptedData = Decrypt(cipherBytes,
                pdb.GetBytes(32), pdb.GetBytes(16));

            // Now we need to turn the resulting byte array into a string. 
            // A common mistake would be to use an Encoding class for that.
            // It does not work 
            // because not all byte values can be represented by characters. 
            // We are going to be using Base64 encoding that is 
            // designed exactly for what we are trying to do. 
            return System.Text.Encoding.Unicode.GetString(decryptedData);
        }

        /// <summary>
        /// Decrypt bytes into bytes using a password 
        /// </summary>
        /// <param name="cipherData"></param>
        /// <param name="Password"></param>
        /// <returns></returns>
        public static byte[] Decrypt(byte[] cipherData, string Password)
        {
            // We need to turn the password into Key and IV. 
            // We are using salt to make it harder to guess our key
            // using a dictionary attack - 
            // trying to guess a password by enumerating all possible words. 
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
                new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
            0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

            // Now get the key/IV and do the Decryption using the 
            //function that accepts byte arrays. 
            // Using PasswordDeriveBytes object we are first getting
            // 32 bytes for the Key 
            // (the default Rijndael key length is 256bit = 32bytes)
            // and then 16 bytes for the IV. 
            // IV should always be the block size, which is by default
            // 16 bytes (128 bit) for Rijndael. 
            // If you are using DES/TripleDES/RC2 the block size is
            // 8 bytes and so should be the IV size. 

            // You can also read KeySize/BlockSize properties off the
            // algorithm to find out the sizes. 
            return Decrypt(cipherData, pdb.GetBytes(32), pdb.GetBytes(16));
        }

        /// <summary>
        /// Decrypt a file into another file using a password 
        /// </summary>
        /// <param name="fileIn"></param>
        /// <param name="fileOut"></param>
        /// <param name="Password"></param>
        public static void Decrypt(string fileIn,
                    string fileOut, string Password)
        {

            // First we are going to open the file streams 
            FileStream fsIn = new FileStream(fileIn,
                        FileMode.Open, FileAccess.Read);
            FileStream fsOut = new FileStream(fileOut,
                        FileMode.OpenOrCreate, FileAccess.Write);

            // Then we are going to derive a Key and an IV from
            // the Password and create an algorithm 
            PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password,
                new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
            0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});
            Rijndael alg = Rijndael.Create();

            alg.Key = pdb.GetBytes(32);
            alg.IV = pdb.GetBytes(16);

            // Now create a crypto stream through which we are going
            // to be pumping data. 
            // Our fileOut is going to be receiving the Decrypted bytes. 
            CryptoStream cs = new CryptoStream(fsOut,
                alg.CreateDecryptor(), CryptoStreamMode.Write);

            // Now will will initialize a buffer and will be 
            // processing the input file in chunks. 
            // This is done to avoid reading the whole file (which can be
            // huge) into memory. 
            int bufferLen = 4096;
            byte[] buffer = new byte[bufferLen];
            int bytesRead;

            do
            {
                // read a chunk of data from the input file 
                bytesRead = fsIn.Read(buffer, 0, bufferLen);

                // Decrypt it 
                cs.Write(buffer, 0, bytesRead);

            } while (bytesRead != 0);

            // close everything 
            cs.Close(); // this will also close the unrelying fsOut stream 
            fsIn.Close();
        }
        /// <summary>
        /// Create String array from a string with delimiter
        /// </summary>
        /// <param name="s"></param>
        /// <param name="delimiter"></param>
        /// <returns></returns>
        public static string[] SplitByString(string s, string delimiter)
        {
            try
            {
                string[] stringSeparators = new string[] { delimiter };
                string[] result;

                result = s.Split(stringSeparators, StringSplitOptions.None);

                return result;
            }
            catch (Exception)
            {
                throw;
            }
        }
        /// <summary>
        /// Get Value in AppSettings
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static string GetAppSettingByKey(string key)
        {
            try
            {
                return ConfigurationManager.AppSettings[key];
            }
            catch
            {
                return null;
            }
        }
        /// <summary>
        /// Get Html Content
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static string GetHtmlContent(string filename)
        {
            StreamReader sr;
            string html;
            sr = File.OpenText(filename);
            html = sr.ReadToEnd();
            sr.Close();

            Regex start = new Regex(@"[\s\S]*<body[^<]*>", RegexOptions.IgnoreCase);
            html = start.Replace(html, "");
            Regex end = new Regex(@"</body[\s\S]*", RegexOptions.IgnoreCase);
            html = end.Replace(html, "");
            return html;
        }
        /// <summary>
        /// Create a Random String
        /// </summary>
        /// <param name="size"></param>
        /// <returns></returns>
        public static string RandomString(int size)
        {
            Random _random = new Random();
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < size; i++)
            {
                //26 letters in the alfabet, ascii + 65 for the capital letters
                builder.Append(Convert.ToChar(Convert.ToInt32(Math.Floor(26 * _random.NextDouble() + 65))));
                //builder.Append((char)_random.Next('A', 'Z' + 1));            

            }
            return builder.ToString().ToLower();

        }
        /// <summary>
        /// Create a Random Number
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public static int RandomNumber(int min, int max)
        {
            Random random = new Random();
            return random.Next(min, max);
        }
        /// <summary>
        /// Encode with MD5
        /// </summary>
        /// <param name="Value"></param>
        /// <returns></returns>
        public static string MD5(string Value)
        {
            byte[] data = System.Text.ASCIIEncoding.ASCII.GetBytes(Value);
            // This is one implementation of the abstract class MD5.
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] result = md5.ComputeHash(data);
            return System.Convert.ToBase64String(result, 0, result.Length);
        }
        /// <summary>
        /// Encode a string to something Javascript will accept. Does not accept a null pointer
        /// </summary>
        public static string EnquoteForClientScript(string s)
        {
            if (string.IsNullOrEmpty(s))
                return s;
            return s.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\'", "\\\'").Replace("\r", "").Replace("\n", "\\n");
        }
        /// <summary>
        /// Encode Special Text
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string EncodeSpecialText(string s)
        {
            if (string.IsNullOrEmpty(s))
                return s;
            return s.Replace("&", "&amp").Replace("<", "&lt").Replace(">", "&gt").Replace("\"", "&quot");
        }
        /// <summary>
        /// Replace Xml Value
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string ReplaceXmlValue(string value)
        {
            return value.Replace("!@#$%^*!", "/").Replace("!@#$%^*", ";");
        }
        /// <summary>
        /// Get Node XML by Name
        /// </summary>
        /// <param name="node"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static XmlNode GetNode(XmlNode node, string name)
        {
            foreach (XmlNode xmlNode in node.ChildNodes)
            {
                if (xmlNode.Name == name)
                    return xmlNode;
            }
            return null;
        }
        /// <summary>
        /// Get list Countries
        /// </summary>
        /// <returns></returns>
        public static DataTable Countries()
        {
            DataTable table = new DataTable();
            table.Columns.Add("Id", typeof(string));
            table.Columns.Add("Country", typeof(string));
            table.Rows.Add("AF", "Afghanistan");
            table.Rows.Add("AL", "Albania");
            table.Rows.Add("DZ", "Algeria");
            table.Rows.Add("AS", "American Samoa");
            table.Rows.Add("AD", "Andorra");
            table.Rows.Add("AO", "Angola");
            table.Rows.Add("AI", "Anguilla");
            table.Rows.Add("AQ", "Antarctica");
            table.Rows.Add("AG", "Antigua And Barbuda");
            table.Rows.Add("AR", "Argentina");
            table.Rows.Add("AM", "Armenia");
            table.Rows.Add("AW", "Aruba");
            table.Rows.Add("AU", "Australia");
            table.Rows.Add("AT", "Austria");
            table.Rows.Add("AZ", "Azerbaijan");
            table.Rows.Add("BS", "Bahamas");
            table.Rows.Add("BH", "Bahrain");
            table.Rows.Add("BD", "Bangladesh");
            table.Rows.Add("BB", "Barbados");
            table.Rows.Add("BY", "Belarus");
            table.Rows.Add("BE", "Belgium");
            table.Rows.Add("BZ", "Belize");
            table.Rows.Add("BJ", "Benin");
            table.Rows.Add("BM", "Bermuda");
            table.Rows.Add("BT", "Bhutan");
            table.Rows.Add("BO", "Bolivia");
            table.Rows.Add("BA", "Bosnia And Herzegowina");
            table.Rows.Add("BW", "Botswana");
            table.Rows.Add("BV", "Bouvet Island");
            table.Rows.Add("BR", "Brazil");
            table.Rows.Add("IO", "British Indian Ocean Territory");
            table.Rows.Add("BN", "Brunei Darussalam");
            table.Rows.Add("BG", "Bulgaria");
            table.Rows.Add("BF", "Burkina Faso");
            table.Rows.Add("BI", "Burundi");
            table.Rows.Add("KH", "Cambodia");
            table.Rows.Add("CM", "Cameroon");
            table.Rows.Add("CA", "Canada");
            table.Rows.Add("CV", "Cape Verde");
            table.Rows.Add("KY", "Cayman Islands");
            table.Rows.Add("CF", "Central African Republic");
            table.Rows.Add("TD", "Chad");
            table.Rows.Add("CL", "Chile");
            table.Rows.Add("CN", "China");
            table.Rows.Add("CX", "Christmas Island");
            table.Rows.Add("CC", "Cocos (Keeling) Islands");
            table.Rows.Add("CO", "Colombia");
            table.Rows.Add("KM", "Comoros");
            table.Rows.Add("CG", "Congo");
            table.Rows.Add("CK", "Cook Islands");
            table.Rows.Add("CR", "Costa Rica");
            table.Rows.Add("CI", "Cote D'Ivoire");
            table.Rows.Add("HR", "Croatia (Local Name: Hrvatska)");
            table.Rows.Add("CU", "Cuba");
            table.Rows.Add("CY", "Cyprus");
            table.Rows.Add("CZ", "Czech Republic");
            table.Rows.Add("DK", "Denmark");
            table.Rows.Add("DJ", "Djibouti");
            table.Rows.Add("DM", "Dominica");
            table.Rows.Add("DO", "Dominican Republic");
            table.Rows.Add("TP", "East Timor");
            table.Rows.Add("EC", "Ecuador");
            table.Rows.Add("EG", "Egypt");
            table.Rows.Add("SV", "El Salvador");
            table.Rows.Add("GQ", "Equatorial Guinea");
            table.Rows.Add("ER", "Eritrea");
            table.Rows.Add("EE", "Estonia");
            table.Rows.Add("ET", "Ethiopia");
            table.Rows.Add("FK", "Falkland Islands (Malvinas)");
            table.Rows.Add("FO", "Faroe Islands");
            table.Rows.Add("FJ", "Fiji");
            table.Rows.Add("FI", "Finland");
            table.Rows.Add("FR", "France");
            table.Rows.Add("GF", "French Guiana");
            table.Rows.Add("PF", "French Polynesia");
            table.Rows.Add("TF", "French Southern Territories");
            table.Rows.Add("GA", "Gabon");
            table.Rows.Add("GM", "Gambia");
            table.Rows.Add("GE", "Georgia");
            table.Rows.Add("DE", "Germany");
            table.Rows.Add("GH", "Ghana");
            table.Rows.Add("GI", "Gibraltar");
            table.Rows.Add("GR", "Greece");
            table.Rows.Add("GL", "Greenland");
            table.Rows.Add("GD", "Grenada");
            table.Rows.Add("GP", "Guadeloupe");
            table.Rows.Add("GU", "Guam");
            table.Rows.Add("GT", "Guatemala");
            table.Rows.Add("GN", "Guinea");
            table.Rows.Add("GW", "Guinea-Bissau");
            table.Rows.Add("GY", "Guyana");
            table.Rows.Add("HT", "Haiti");
            table.Rows.Add("HM", "Heard And Mc Donald Islands");
            table.Rows.Add("VA", "Holy See (Vatican City State)");
            table.Rows.Add("HN", "Honduras");
            table.Rows.Add("HK", "Hong Kong");
            table.Rows.Add("HU", "Hungary");
            table.Rows.Add("IS", "Icel And");
            table.Rows.Add("IN", "India");
            table.Rows.Add("ID", "Indonesia");
            table.Rows.Add("IR", "Iran (Islamic Republic Of)");
            table.Rows.Add("IQ", "Iraq");
            table.Rows.Add("IE", "Ireland");
            table.Rows.Add("IL", "Israel");
            table.Rows.Add("IT", "Italy");
            table.Rows.Add("JM", "Jamaica");
            table.Rows.Add("JP", "Japan");
            table.Rows.Add("JO", "Jordan");
            table.Rows.Add("KZ", "Kazakhstan");
            table.Rows.Add("KE", "Kenya");
            table.Rows.Add("KI", "Kiribati");
            table.Rows.Add("KP", "Korea, Dem People'S Republic");
            table.Rows.Add("KR", "Korea, Republic Of");
            table.Rows.Add("KW", "Kuwait");
            table.Rows.Add("KG", "Kyrgyzstan");
            table.Rows.Add("LA", "Lao People'S Dem Republic");
            table.Rows.Add("LV", "Latvia");
            table.Rows.Add("LB", "Lebanon");
            table.Rows.Add("LS", "Lesotho");
            table.Rows.Add("LR", "Liberia");
            table.Rows.Add("LY", "Libyan Arab Jamahiriya");
            table.Rows.Add("LI", "Liechtenstein");
            table.Rows.Add("LT", "Lithuania");
            table.Rows.Add("LU", "Luxembourg");
            table.Rows.Add("MO", "Macau");
            table.Rows.Add("MK", "Macedonia");
            table.Rows.Add("MG", "Madagascar");
            table.Rows.Add("MW", "Malawi");
            table.Rows.Add("MY", "Malaysia");
            table.Rows.Add("MV", "Maldives");
            table.Rows.Add("ML", "Mali");
            table.Rows.Add("MT", "Malta");
            table.Rows.Add("MH", "Marshall Islands");
            table.Rows.Add("MQ", "Martinique");
            table.Rows.Add("MR", "Mauritania");
            table.Rows.Add("MU", "Mauritius");
            table.Rows.Add("YT", "Mayotte");
            table.Rows.Add("MX", "Mexico");
            table.Rows.Add("FM", "Micronesia, Federated States");
            table.Rows.Add("MD", "Moldova, Republic Of");
            table.Rows.Add("MC", "Monaco");
            table.Rows.Add("MN", "Mongolia");
            table.Rows.Add("MS", "Montserrat");
            table.Rows.Add("MA", "Morocco");
            table.Rows.Add("MZ", "Mozambique");
            table.Rows.Add("MM", "Myanmar");
            table.Rows.Add("NA", "Namibia");
            table.Rows.Add("NR", "Nauru");
            table.Rows.Add("NP", "Nepal");
            table.Rows.Add("NL", "Netherlands");
            table.Rows.Add("AN", "Netherlands Ant Illes");
            table.Rows.Add("NC", "New Caledonia");
            table.Rows.Add("NZ", "New Zealand");
            table.Rows.Add("NI", "Nicaragua");
            table.Rows.Add("NE", "Niger");
            table.Rows.Add("NG", "Nigeria");
            table.Rows.Add("NU", "Niue");
            table.Rows.Add("NF", "Norfolk Island");
            table.Rows.Add("MP", "Northern Mariana Islands");
            table.Rows.Add("NO", "Norway");
            table.Rows.Add("OM", "Oman");
            table.Rows.Add("PK", "Pakistan");
            table.Rows.Add("PW", "Palau");
            table.Rows.Add("PA", "Panama");
            table.Rows.Add("PG", "Papua New Guinea");
            table.Rows.Add("PY", "Paraguay");
            table.Rows.Add("PE", "Peru");
            table.Rows.Add("PH", "Philippines");
            table.Rows.Add("PN", "Pitcairn");
            table.Rows.Add("PL", "Poland");
            table.Rows.Add("PT", "Portugal");
            table.Rows.Add("PR", "Puerto Rico");
            table.Rows.Add("QA", "Qatar");
            table.Rows.Add("RE", "Reunion");
            table.Rows.Add("RO", "Romania");
            table.Rows.Add("RU", "Russian Federation");
            table.Rows.Add("RW", "Rwanda");
            table.Rows.Add("KN", "Saint K Itts And Nevis");
            table.Rows.Add("LC", "Saint Lucia");
            table.Rows.Add("VC", "Saint Vincent, The Grenadines");
            table.Rows.Add("WS", "Samoa");
            table.Rows.Add("SM", "San Marino");
            table.Rows.Add("ST", "Sao Tome And Principe");
            table.Rows.Add("SA", "Saudi Arabia");
            table.Rows.Add("SN", "Senegal");
            table.Rows.Add("SC", "Seychelles");
            table.Rows.Add("SL", "Sierra Leone");
            table.Rows.Add("SG", "Singapore");
            table.Rows.Add("SK", "Slovakia (Slovak Republic)");
            table.Rows.Add("SI", "Slovenia");
            table.Rows.Add("SB", "Solomon Islands");
            table.Rows.Add("SO", "Somalia");
            table.Rows.Add("ZA", "South Africa");
            table.Rows.Add("GS", "South Georgia , S Sandwich Is.");
            table.Rows.Add("ES", "Spain");
            table.Rows.Add("LK", "Sri Lanka");
            table.Rows.Add("SH", "St. Helena");
            table.Rows.Add("PM", "St. Pierre And Miquelon");
            table.Rows.Add("SD", "Sudan");
            table.Rows.Add("SR", "Suriname");
            table.Rows.Add("SJ", "Svalbard, Jan Mayen Islands");
            table.Rows.Add("SZ", "Sw Aziland");
            table.Rows.Add("SE", "Sweden");
            table.Rows.Add("CH", "Switzerland");
            table.Rows.Add("SY", "Syrian Arab Republic");
            table.Rows.Add("TW", "Taiwan");
            table.Rows.Add("TJ", "Tajikistan");
            table.Rows.Add("TZ", "Tanzania, United Republic Of");
            table.Rows.Add("TH", "Thailand");
            table.Rows.Add("TG", "Togo");
            table.Rows.Add("TK", "Tokelau");
            table.Rows.Add("TO", "Tonga");
            table.Rows.Add("TT", "Trinidad And Tobago");
            table.Rows.Add("TN", "Tunisia");
            table.Rows.Add("TR", "Turkey");
            table.Rows.Add("TM", "Turkmenistan");
            table.Rows.Add("TC", "Turks And Caicos Islands");
            table.Rows.Add("TV", "Tuvalu");
            table.Rows.Add("UG", "Uganda");
            table.Rows.Add("UA", "Ukraine");
            table.Rows.Add("AE", "United Arab Emirates");
            table.Rows.Add("UK", "United Kingdom");
            table.Rows.Add("US", "United States");
            table.Rows.Add("UM", "United States Minor Is.");
            table.Rows.Add("UY", "Uruguay");
            table.Rows.Add("UZ", "Uzbekistan");
            table.Rows.Add("VU", "Vanuatu");
            table.Rows.Add("VE", "Venezuela");
            table.Rows.Add("VN", "Viet Nam");
            table.Rows.Add("VG", "Virgin Islands (British)");
            table.Rows.Add("VI", "Virgin Islands (U.S.)");
            table.Rows.Add("WF", "Wallis And Futuna Islands");
            table.Rows.Add("EH", "Western Sahara");
            table.Rows.Add("YE", "Yemen");
            table.Rows.Add("YU", "Yugoslavia");
            table.Rows.Add("ZR", "Zaire");
            table.Rows.Add("ZM", "Zambia");
            table.Rows.Add("ZW", "Zimbabwe");
            return table;
        }

        /// <summary>
        /// Send Email
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="enableSSL"></param>
        /// <param name="displayName"></param>
        /// <param name="fromAddress"></param>
        /// <param name="toAddress"></param>
        /// <param name="subject"></param>
        /// <param name="body"></param>
        /// <param name="cc"></param>
        /// <param name="bcc"></param>
        /// <param name="filesPath"></param>
        /// <returns>return true if successful, return false if unsuccessful</returns>
        public static bool SendEmail(string host, int port, string username, string password, bool enableSSL, string displayName, string fromAddress, string toAddress, string subject, string body, string cc, string bcc, string filesPath)
        {
            try
            {
                MailMessage mailMessage = BuildMailMessage(displayName, fromAddress, toAddress, subject, body);
                if (!String.IsNullOrEmpty(filesPath))
                {
                    string[] attachs = filesPath.Split(';');
                    foreach (string attach in attachs)
                    {
                        var stream = new WebClient().OpenRead(attach);
                        Attachment attachment = new Attachment(stream, attach.Substring(attach.LastIndexOf("\\") + 1));
                        mailMessage.Attachments.Add(attachment);
                    }
                }

                if (!String.IsNullOrEmpty(cc))
                {
                    string[] arr_cc = cc.Split(';');
                    foreach (string _cc in arr_cc)
                    {
                        MailAddress copy = new MailAddress(_cc);
                        mailMessage.CC.Add(copy);
                    }

                }
                if (!String.IsNullOrEmpty(bcc))
                {
                    string[] arr_bcc = bcc.Split(';');
                    foreach (var _bcc in arr_bcc)
                    {
                        MailAddress mail = new MailAddress(_bcc);
                        mailMessage.Bcc.Add(mail);
                    }
                }
                SmtpClient smtp = new SmtpClient { Host = host, Port = port };

                NetworkCredential credential = new NetworkCredential(username, password);
                smtp.Credentials = credential;
                smtp.EnableSsl = enableSSL;
                smtp.Send(mailMessage);
                mailMessage.Dispose();
                return true;
            }
            catch //(Exception ex)
            {
                return false;
            }
        }
        public static bool SendEmail(string host, int port, string username, string password, bool enableSSL, string displayName, string fromAddress, string toAddress, string subject, string body, string cc, string bcc)
        {
            return SendEmail(host, port, username, password, enableSSL, displayName, fromAddress, toAddress, subject, body, cc, bcc, null);
        }
        public static bool SendEmail(string host, int port, string username, string password, bool enableSSL, string displayName, string fromAddress, string toAddress, string subject, string body, string cc)
        {
            return SendEmail(host, port, username, password, enableSSL, displayName, fromAddress, toAddress, subject, body, cc, null, null);
        }
        public static bool SendEmail(string host, int port, string username, string password, bool enableSSL, string displayName, string fromAddress, string toAddress, string subject, string body)
        {
            return SendEmail(host, port, username, password, enableSSL, displayName, fromAddress, toAddress, subject, body, null, null, null);
        }
        /// <summary>
        /// Build Email Content
        /// </summary>
        /// <param name="displayName"></param>
        /// <param name="fromAddress"></param>
        /// <param name="toAddress"></param>
        /// <param name="subject"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        private static MailMessage BuildMailMessage(string displayName, string fromAddress, string toAddress, string subject, string body)
        {
            MailMessage message = new MailMessage
            {
                From = new MailAddress(fromAddress, displayName),
                Subject = subject,
                Body = body,
                BodyEncoding = Encoding.UTF8,
                IsBodyHtml = true,
            };

            string[] tos = toAddress.Split(';');
            foreach (string to in tos)
                message.To.Add(new MailAddress(to));

            return message;
        }
    }
}
